package com.rede.didiok.user.restapi;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.rede.didiok.common.annotion.AvoidRepeatableCommit.AvoidRepeatableCommit;
import com.rede.didiok.common.annotion.FeignSecurity.FeignSecurity;
import com.rede.didiok.common.annotion.SubmitVerify.SubmitVerify;
import com.rede.didiok.common.annotion.log.BussinessLog;
import com.rede.didiok.common.constant.conf.MessageConf;
import com.rede.didiok.common.constant.conf.SysConf;
import com.rede.didiok.common.constant.global.Constants;
import com.rede.didiok.common.dto.admin.AdminDto;
import com.rede.didiok.common.dto.community.UserMomentDto;
import com.rede.didiok.common.dto.rank.RankMemberDto;
import com.rede.didiok.common.dto.user.SignInRecordDto;
import com.rede.didiok.common.dto.user.UserDto;
import com.rede.didiok.common.dto.user.UserWatchDto;
import com.rede.didiok.common.enums.BehaviorEnum;
import com.rede.didiok.common.enums.LoginTypeEnum;
import com.rede.didiok.common.exception.ThrowableUtils;
import com.rede.didiok.common.exception.exceptionType.FeignException;
import com.rede.didiok.common.exception.exceptionType.QueryException;
import com.rede.didiok.common.feign.AdminFeignClient;
import com.rede.didiok.common.feign.CommunityFeignClient;
import com.rede.didiok.common.feign.RankFeignClient;
import com.rede.didiok.common.holder.RequestHolder;
import com.rede.didiok.common.utils.*;
import com.rede.didiok.common.validator.group.GetList;
import com.rede.didiok.common.validator.group.Insert;
import com.rede.didiok.user.entity.UserEntity;
import com.rede.didiok.user.service.*;

/**
 * 关于我 RestApi
 *
 * @author 陌溪
 * @date 2018年11月12日14:51:54
 */
@RestController
@RequestMapping("/about/user")
@Api(value = "关于我相关接口", tags = {"关于我相关接口"})
@Slf4j
public class UserCenterRestApi {

    @Resource
    private AdminFeignClient adminFeignClient;
    @Resource
    private RankFeignClient rankFeignClient;
    @Resource
    private UserService userService;
    @Resource
    private UserWatchService userWatchService;
    @Resource
    private SignInRecordService signInRecordService;
    @Resource
    private CommunityFeignClient communityFeignClient;
//    @Resource
//    private CollectService collectService;
//    @Resource
//    private UserEquityRecordService userEquityRecordService;
    @Autowired
    private RedisUtil redisUtil;
    @Resource
    private WebVisitService webVisitService;

    @Resource
    private MedalService medalService;


    @ApiOperation(value = "通过ID获取用户【包含用户和管理员】", notes = "通过ID获取用户")
    @GetMapping("/getUserByUid")
    public String getUserByUid(HttpServletRequest request, @ApiParam(name = "adminUid", value = "管理员uid", required = false) @RequestParam(name = "adminUid", required = false, defaultValue = "") String adminUid,
                               @ApiParam(name = "userUid", value = "用户uid", required = false) @RequestParam(name = "userUid", required = false, defaultValue = "") String userUid,
                               @ApiParam(name = "refresh", value = "是否强制刷新", required = false) @RequestParam(name = "refresh", required = false, defaultValue = "false") boolean refresh) throws ExecutionException, InterruptedException {
        Object currentUserUid = request.getAttribute(SysConf.USER_UID);
        if (StringUtils.isNotEmpty(adminUid)) {
            List<String> adminUidList = new ArrayList<>();
            adminUidList.add(adminUid);
            R result = adminFeignClient.getAdminListByUids(adminUidList);
            List<AdminDto> adminDtoList = null;
            if (result.getCode() == 0) {
                adminDtoList = result.getData(new TypeReference<List<AdminDto>>(){});
            }else {
                throw new FeignException("feign调用异常（通过 ids 获取管理员列表）：失败");
            }
            if (adminDtoList.size() == 0) {
                throw new QueryException(MessageConf.PARAM_INCORRECT);
            }
            // 默认没有关注用户
            Boolean isWatchUser = false;
            if (currentUserUid != null) {
                UserWatchDto userWatchDto = new UserWatchDto();
                userWatchDto.setCreateUserUid(currentUserUid.toString());
                userWatchDto.setToUserUid(adminUid);
                isWatchUser = userWatchService.checkUserWatch(userWatchDto);
            } else {
                log.info("前端用户未登录");
            }
            // 获取管理员
            AdminDto adminDto = adminDtoList.get(0);
            adminDto.setIsWatchUser(isWatchUser);
            return ResultUtil.successWithData(adminDto);
        } else if (StringUtils.isNotEmpty(userUid)) {
            List<String> userUidList = new ArrayList<>();
            userUidList.add(userUid);
            List<UserEntity> userList = userService.getUserListAndAvatarByIds(userUidList);
            if (userList.size() > 0) {
                return ResultUtil.successWithData(userList.get(0));
            }else {
                return ResultUtil.errorWithMessage("该用户不存在");
            }
//            //从Redis中获取用户卡片信息
//            String jsonResult = redisUtil.get(RedisConf.USER_CARD_DETAIL + Constants.SYMBOL_COLON + userUid);
//            if (StringUtils.isEmpty(jsonResult) || refresh) {
//                if (userList.size() > 0) {
//                    // 创建一个最大线程数为10的线程池
//                    ExecutorService threadPool = Executors.newFixedThreadPool(12);
//                    List<Callable<Void>> tasks = new ArrayList<>(); // 定义任务列表
//                    UserEntity user = userList.get(0);
//
//                    // 添加文章数设置任务
//                    tasks.add(() -> {
//                        // 设置文章数
//                        Integer rankMemberPublishCount = userService.getRankMemberPublishCount(user.getUid());
//                        user.setRankMemberPublishCount(rankMemberPublishCount);
//                        return null;
//                    });
////
////                    // 添加阅读数设置任务
////                    tasks.add(() -> {
////                        // 设置阅读数
////                        // 默认没有关注用户
////                        boolean isWatchUser = false;
////                        if (currentUserUid != null) {
////                            UserWatchDto userWatchDto = new UserWatchDto();
////                            userWatchDto.setCreateUserUid(currentUserUid.toString());
////                            userWatchDto.setToUserUid(userUid);
////                            isWatchUser = userWatchService.checkUserWatch(userWatchDto);
////                        } else {
////                            log.info("前端用户未登录");
////                        }
////                        user.setIsWatchUser(isWatchUser);
////                        return null;
////                    });
////
////                    // 添加关注人数设置任务
////                    tasks.add(() -> {
////                        // 获取关注人数
////                        UserWatchDto watches = new UserWatchDto();
////                        watches.setCreateUserUid(userUid);
////                        user.setUserWatchCount(userWatchService.getUserWatchCount(watches));
////                        return null;
////                    });
////
////                    // 添加粉丝人数设置任务
////                    tasks.add(() -> {
////                        UserWatchDto followes = new UserWatchDto();
////                        followes.setToUserUid(userUid);
////                        user.setUserFollowCount(userWatchService.getUserWatchCount(followes));
////                        return null;
////                    });
//
//                    // 添加动态数量设置任务
//                    tasks.add(() -> {
//                        UserMomentDto userMomentDto = new UserMomentDto();
//                        userMomentDto.setCreateUserUid(userUid);
//                        Integer userMomentCount = communityFeignClient.getUserMomentCount(userMomentDto.getCreateUserUid());
//                        user.setUserMomentCount(userMomentCount);
//                        return null;
//                    });
//
//                    // 添加评论数量设置任务
//                    tasks.add(() -> {
//                        MemberCommentDto commentDto = new MemberCommentDto();
//                        commentDto.setCreateUserUid(userUid);
//                        user.setMemberCommentCount(rankFeignClient.getCommentCount(commentDto.getCreateUserUid(), commentDto.getMemberUid(), commentDto.getToUserUid()));
//                        return null;
//                    });
//
//                    // 添加用户动态评论数量设置任务
//                    tasks.add(() -> {
//                        MomentCommentDto commentDto = new MomentCommentDto();
//                        commentDto.setCreateUserUid(userUid);
//                        user.setMomentCommentCount(communityFeignClient.getCommentCount(commentDto.getCreateUserUid(), commentDto.getMomentUid(), commentDto.getToUserUid()));
//                        return null;
//                    });
//
//                    threadPool.invokeAll(tasks); // 并发执行所有任务
//                    threadPool.shutdown(); // 关闭线程池
//
//                    // 将用户卡片数据 存储到 redis
//                    redisUtil.setEx(RedisConf.USER_CARD_DETAIL + Constants.SYMBOL_COLON + userUid, JsonUtils.objectToJson(user), 10, TimeUnit.MINUTES);
//                    return ResultUtil.successWithData(user);
//                } else {
//                    return ResultUtil.errorWithMessage("该用户不存在");
//                }
//            } else {
//                UserDto user = JsonUtils.jsonToPojo(jsonResult, UserDto.class);
//                return ResultUtil.successWithData(user);
//            }
        }
//        log.info("通过用户获取榜单成员列表");
        return ResultUtil.errorWithMessage(MessageConf.PARAM_INCORRECT);
    }

    @ApiOperation(value = "通过ID获取用户个人中心统计信息", notes = "通过ID获取用户个人中心统计信息")
    @GetMapping("/getUserCenterByUid")
    public String getInfoByUid(HttpServletRequest request,
                               @ApiParam(name = "adminUid", value = "管理员uid", required = false) @RequestParam(name = "adminUid", required = false, defaultValue = "") String adminUid,
                               @ApiParam(name = "userUid", value = "用户uid", required = false) @RequestParam(name = "userUid", required = false, defaultValue = "") String userUid) {
        if (StringUtils.isNotEmpty(adminUid)) {


            // 获取发表的文章数
            RankMemberDto rankMemberDto = new RankMemberDto();
            rankMemberDto.setAdminUid(adminUid);
            Map<String, Integer> map = new HashMap<>();
            map.put("rankMemberCount", rankFeignClient.getRankMemberCountByAdminOrUser(adminUid, ""));

            // 获取关注人数
            UserWatchDto watches = new UserWatchDto();
            watches.setCreateUserUid(adminUid);
            map.put("watchCount", userWatchService.getUserWatchCount(watches));
            // 获取粉丝人数
            UserWatchDto followes = new UserWatchDto();
            followes.setToUserUid(adminUid);
            map.put("followCount", userWatchService.getUserWatchCount(followes));
            // 超管没有动态和问题数
            map.put("momentCount", 0);
            map.put("problemCount", 0);
            return ResultUtil.successWithData(map);

        } else if (StringUtils.isNotEmpty(userUid)) {
            // todo 修改成多线程同时处理

            RankMemberDto rankMemberDto = new RankMemberDto();
            rankMemberDto.setCreateUserUid(userUid);
            Map<String, Integer> map = new HashMap<>();
            map.put("rankMemberCount", rankFeignClient.getRankMemberCountByAdminOrUser("", userUid));
//
//            // 获取关注人数
//            UserWatchDto watches = new UserWatchDto();
//            watches.setCreateUserUid(userUid);
//            map.put("watchCount", userWatchService.getUserWatchCount(watches));
//
//            // 获取粉丝人数
//            UserWatchDto followes = new UserWatchDto();
//            followes.setToUserUid(userUid);
//            map.put("followCount", userWatchService.getUserWatchCount(followes));

            // 设置动态数量
            UserMomentDto userMomentDto = new UserMomentDto();
            userMomentDto.setCreateUserUid(userUid);
            map.put("momentCount", communityFeignClient.getUserMomentCount(userMomentDto.getCreateUserUid()));

            return ResultUtil.successWithData(map);
        }

        log.info("通过ID获取用户个人中心信息");
        return ResultUtil.errorWithMessage(MessageConf.PARAM_INCORRECT);
    }

    @ApiOperation(value = "获取用户关注列表", notes = "获取用户关注列表")
    @PostMapping("/getUserWatchList")
    public String getUserWatchList(@Validated({GetList.class}) @RequestBody UserWatchDto userWatchDto, BindingResult result) {
        ThrowableUtils.checkParamArgument(result);
        log.info("获取用户关注列表");
        return ResultUtil.successWithData(userWatchService.getPageList(userWatchDto));
    }

    @ApiOperation(value = "判断当前登录用户，是否关注过某人", notes = "判断当前登录用户，是否关注过某人")
    @PostMapping("/checkCurrentUserWatch")
    public String checkCurrentUserWatch(@RequestBody UserWatchDto userWatchDto) {
        log.info("获取用户关注列表");
        return ResultUtil.successWithData(userWatchService.checkCurrentUserWatch(userWatchDto));
    }


    @AvoidRepeatableCommit(timeout = 5000)
    @ApiOperation(value = "关注某人", notes = "关注某人")
    @PostMapping("/addUserWatch")
    public String addUserWatch(@Validated({Insert.class}) @RequestBody UserWatchDto userWatchDto, BindingResult result) {
        ThrowableUtils.checkParamArgument(result);
        log.info("关注某人");
        return userWatchService.addUserWatch(userWatchDto);
    }

    @AvoidRepeatableCommit(timeout = 5000)
    @ApiOperation(value = "取消关注某人", notes = "取消关注某人")
    @PostMapping("/deleteUserWatch")
    public String deleteUserWatch(@Validated({Insert.class}) @RequestBody UserWatchDto userWatchDto, BindingResult result) {
        ThrowableUtils.checkParamArgument(result);
        log.info("取消关注某人");
        return userWatchService.deleteUserWatch(userWatchDto);
    }

    @AvoidRepeatableCommit
    @BussinessLog(value = "用户签到", behavior = BehaviorEnum.SIGN_IN)
    @ApiOperation(value = "用户签到", notes = "用户签到")
    @PostMapping("/userSignIn")
    public String userSignIn() {
        log.info("用户签到");
        String userUid = RequestHolder.getUserUid();
        if (StringUtils.isEmpty(userUid)) {
            throw new QueryException(Constants.USER_UID_EMPTY);
        }
        return signInRecordService.userSignIn(userUid);
    }

    @ApiOperation(value = "微信用户签到回调接口", notes = "微信用户签到回调接口")
    @PostMapping(value = "/wechatUserSignIn")
    public String wechatUserLogin(@RequestParam(value = "openid") String openid, @RequestParam(value = "sign") String sign) {

        // 签名验证
        Map<String, Object> data = new HashMap<>();
        data.put("openid", openid);
        data.put("sign", sign);
        if (!SignUtils.isSignEquals(data)) {
            return ResultUtil.errorWithMessage("签名校验失败");
        }

        UserEntity user = userService.getUserByUuidAndSource(openid, LoginTypeEnum.WECHAT.getName());
        if (user != null) {
            return signInRecordService.userSignIn(user.getUid());
        }
        return ResultUtil.errorWithMessage("用户不存在");
    }

    @BussinessLog(value = "用户补签", behavior = BehaviorEnum.RETROACTIVE_SIGN_IN)
    @ApiOperation(value = "用户补签", notes = "用户补签")
    @PostMapping("/retroactive")
    public String retroactive(@RequestBody SignInRecordDto signInRecordDto) {
        log.info("用户补签");
        return signInRecordService.retroactive(signInRecordDto);
    }

    // here TODO
    @ApiOperation(value = "用户当月签到信息", notes = "用户当月签到信息")
    @GetMapping("/signDataByUserUid")
    public String signDataByUserUid(@ApiParam(name = "refresh", value = "是否刷新") @RequestParam(name = "refresh", required = false, defaultValue = "false") Boolean refresh,
                                    @ApiParam(name = "dateStr", value = "选择日期") @RequestParam(name = "dateStr", required = false) String dateStr) {
        log.info("用户当月签到信息");
        return signInRecordService.signDataByUserUid(refresh, dateStr);
    }

    @ApiOperation(value = "获取登录用户积分", notes = "获取登录用户积分")
    @PostMapping("/getCurrentUserCredits")
    public String getCurrentUserCredits(@ApiParam(name = "refresh", value = "是否刷新") @RequestParam(name = "refresh", required = false, defaultValue = "false") Boolean refresh) {
        log.info("获取用户积分");
        return ResultUtil.successWithData(userService.getCurrentUserCredits(refresh));
    }

    @SubmitVerify
    @AvoidRepeatableCommit(timeout = 30000)
    @BussinessLog(value = "更新背景图片", behavior = BehaviorEnum.UPDATE_BACKGROUND_IMAGE)
    @ApiOperation(value = "更新背景图片", notes = "更新当前用户背景图片")
    @PostMapping("/updateCurrentUserBackgroundImage")
    public String updateCurrentUserBackgroundImage(@RequestBody UserDto userDto) {
        log.info("更新背景图片");
        return userService.updateCurrentUserBackgroundImage(userDto);
    }


    @BussinessLog(value = "搜索群聊用户", behavior = BehaviorEnum.SEARCH_USER_LIST)
    @ApiOperation(value = "搜索群聊用户", notes = "搜索群聊用户")
    @PostMapping("/getUserList")
    public String getUserList(@RequestBody UserDto userDto) {
        String userUid = RequestHolder.getUserUid();
        if (StringUtils.isEmpty(userUid)) {
            throw new QueryException(Constants.USER_UID_EMPTY);
        }
        log.info("搜索群聊用户");
        userDto.setPageSize(10L);
        IPage<UserEntity> userIPage = userService.getPageList(userDto);
        List<UserEntity> userList = userService.convertUserList(userIPage.getRecords());
        List<UserEntity> newUserList = new ArrayList<>();
        for (UserEntity user : userList) {
            // 排除自己
            if (user.getUid().equals(userUid)) {
                continue;
            }
            newUserList.add(user);
        }
        userIPage.setRecords(newUserList);
        return ResultUtil.successWithData(userIPage);
    }

    @FeignSecurity
    @ApiOperation(value = "获取用户列表", notes = "获取用户列表")
    @PostMapping("/getUserListByPage")
    public List<UserEntity> getUserListByPage(@RequestBody UserDto userDto) {
        log.info("获取用户列表");
        IPage<UserEntity> userIPage = userService.getPageList(userDto);
        return userService.convertUserList(userIPage.getRecords());
    }

    /**
     * 查询积分总榜
     * @return
     */
    @ApiOperation(value = "查询积分总榜", notes = "查询积分总榜")
    @GetMapping(value = "/getLeaderAll")
    public String getLeaderAll(@ApiParam(name = "refresh", value = "是否刷新配置", required = false) @RequestParam(name = "refresh", required = false, defaultValue = "false") Boolean refresh) {
        List<UserEntity> leaderAll = userService.getLeaderAll(refresh);
        return ResultUtil.result(SysConf.SUCCESS, leaderAll);
    }

    /**
     * 获取当前用户钱包金额
     * @return
     */
    @ApiOperation(value = "获取当前用户钱包金额", notes = "获取当前用户钱包金额")
    @PostMapping("/getCurrentUserAmount")
    public String getCurrentUserAmount() {
        log.info("获取当前用户钱包金额");
        String userUidStr = RequestHolder.getUserUid();
        if (StringUtils.isEmpty(userUidStr)) {
            throw new QueryException(Constants.USER_UID_EMPTY);
        }
        return ResultUtil.successWithData(userService.getUserAmount(userUidStr));
    }
}

